jsx3.require("jsx3.gui.Matrix");

/**
 * Extension of the <code>jsx3.gui.Matrix</code> class, for use in the ActiveMatrix Plugin Framework, to provide a benchmarking hook for paint calls.
 */
jsx3.Class.defineClass("com.gix.gui.Matrix", jsx3.gui.Matrix, null, function (matrix) {


	var LOG = jsx3.util.Logger.getLogger(matrix.jsxclass.getName());
	
    /**
     * instance initializer
     * @param strName {String} unique name distinguishing this object from all other JSX GUI objects in the JSX application
     */
    matrix.init = function(strName) {
        this.jsxsuper(strName);
    };
	
// ***********************************************+
// **************** BENCMARK LOGIC ***************|
// ***********************************************+

    /**
     * Updates the view of this object by calling <code>paint()</code> and replacing the current view with the
     * returned HTML. This method has no effect if this object is not currently displayed.  Also logs basic benchmarking
     * of the repaint to the BENCHMARK logger, at the debug log level.
     * @return {String} the result of calling <code>paint()</code> or <code>null</code> if this object is not displayed.
     * @see #paint()
     */
    matrix.prototype.repaint = function() {
        var before = new Date().getTime();
        var dump = this.jsxsuper();
        var since = new Date().getTime() - before
        tibco.admin.util.Log.BENCHMARK.debug("Repainting the matrix " + this.getName() + " takes about " + since + " ms");
        return dump
    };
	

// ***********************************************+
// ************** EMPTY MATRIX LOGIC *************|
// ***********************************************+
	
	
	/**
	* Paints only the data rows.
	* Call our function when the data body has been repainted.
	*/	
	matrix.prototype.repaintData = function() {
		LOG.debug(this.getName() + "  repaintData");
		this.jsxsuper();
		this.updateNullListMessageBlock();
	}
	
	/**
	* A hook that subclasses of Painted may override in order to perform additional manipulation of the HTML DOM created by the paint method.
	* Call our function when the whole matrix has been repainted.
	*/	
	matrix.prototype.onAfterPaint = function(objGUI) {
		LOG.debug(this.getName() + " onAfterPaint");
		this.updateNullListMessageBlock();
		this.jsxsuper(objGUI);
	}
	
	
	/**
	* This function is called upon a each paint
	* Determine whether there is no row. If so, show a message on top of the matrix.
	*/
	matrix.prototype.updateNullListMessageBlock = function() {
		
		LOG.debug(this.getName() + " updateNullListMessageBlock");
		
		//get our parent (this should be a block)
		var objParent = this.getParent();

		//if the paging model use 2 paints (one for the outterbox, then the other one for the data)
		//skip the first paint because at the first paint, the date is not loaded and therefore we cannot
		//know the number of records.
		if ((this.getPagingModel() != jsx3.gui.Matrix.PAGING_OFF) && !this._firstPaint) {
			LOG.debug(this.getName() + " this is the first paint of a 2-pass matrix. skip it");
			this._firstPaint = true;
			return;
		}

		//get the number of row (there is no provided better way to get the number of rows from the Matrix)
		//this calls a XSLT Tranform operation
		if (this.getSortedIds().length > 0) {
			
			//the matrix is not empty, remove the mask if it's present
			if (objParent._masked) {
				LOG.debug(this.getName() + " Removing the mask since the record count > 0.");
				objParent._masked = false;
				objParent.hideMask();
			}
		}
		else {
			//the matrix is empty -> create or update the mask
			
			LOG.debug(this.getName() + " Record count is 0, Checking whether a NullList Message exists for this matrix.");
			
			//get the div containing the message
			var objNullListMessage = this._getFormattedNullListMessage();

			if (objNullListMessage != null) {
				LOG.debug(this.getName() + " NullList Message exists. Inserting the message as the record count is 0.");
				
				//show the mask
				objParent.showMask();
				objParent._masked = true;
				
				//customize the mask (no background, no busy cursor)
				var objMask = objParent.getLastChild();
 				objMask
					.setDynamicProperty("jsxbg",null)
					.setPadding("")
					.setBackground("")
					.setDynamicProperty("jsxbgcolor")
					.setBackgroundColor("")
					.setDynamicProperty("jsxcursor", null)
					.setCursor("") 
					.setText(objNullListMessage, false);
				//repaint the mask
				objMask.repaint();
			}
		}
	}
   
   /**
   * Returns the message shown when the matrix is empty (when there is not row to be shown)
   * Can be null if it is not set.
   * @return {String} or null
   */
	matrix.prototype.getNullListMessage = function() {
		return this.jsxnulllistmessage;
	}
	
   /**
   * Set the message shown when the matrix is empty (when there is not row to be shown)
   * Set null to disable the message.
   * @return {String} or null
   */
	matrix.prototype.setNullListMessage = function(strNullListMessage) {
		this.jsxnulllistmessage = strNullListMessage;
		//update the formatted message
		this._createFormattedNullListMessage();
	}
	
   /**
   * Get the XML DIV object shown when the matrix is empty (when there is not row to be shown)
   * @return {jsx3.xml.Document}
   * @private
   */
   matrix.prototype._getFormattedNullListMessage = function() {
	   	if (this.getNullListMessage() != null && this._formattedNullListMessage == null)
		   this._createFormattedNullListMessage();
		return this._formattedNullListMessage;
	}
	
   /**
   * Update the XML DIV object shown when the matrix is empty (when there is not row to be shown)
   * @param strNullListMessage  {String} the null list message
   * @private
   */
	matrix.prototype._createFormattedNullListMessage = function() {
		
		this._formattedNullListMessage =  new jsx3.xml.Document().loadXML(
			'<div style="position:absolute; top:50%; height:10em; width:50%; left:25%" >' +
				this.getNullListMessage() +
			'</div>');
	}
	
// ***********************************************+
// **************** SPYGLASS LOGIC ***************|
// ***********************************************+

    /**
     * Displays a basic default spyglass for a hovered cell (if called from the spy event).  The format of this spyglass
     * is <code>ATTRIBUTE: VALUE</code>.  Override this function, or call a custom function from the spy event for customized
     * spyglass behavior.
     * @param strRECORDID  {String} CDF record id for spied row
     * @param objCOLUMN  {jsx3.gui.Matrix.Column} - the column that received the spy action
     * @return {String}
     */
    matrix.prototype.spyRecord = function(strRECORDID, objCOLUMN) {
        var record = this.getXML().selectSingleNode("//record[@jsxid = '" + strRECORDID + "']") ;
        if (!record)
            return false;
        var path = objCOLUMN.getPath();
        if (path == "checked")
            return  false;
        var dummy = this.getContentElement(strRECORDID, objCOLUMN.getPath()).
                innerHTML.replace(/&nbsp;\s*$/ig, "").replace(/name=/ig, "").replace(/id=/ig, "");
        if (!dummy)
            return false;

        var UA = navigator.userAgent.toLowerCase();
        var isOpera = UA.indexOf("opera")!=-1;
        var isIE = UA.indexOf("msie")!=-1&&(document.all&&!isOpera);
        var isKon = UA.indexOf("konqueror")!=-1;
        var isSafari = UA.indexOf("safari")!=-1||isKon;
        var tempText = "<b>" + objCOLUMN.getText() + "</b>: " + dummy;

        function escapeSpecialChars(strText)
        {
            return strText.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
        }

        function escapeEntities(strText)
        {
            return strText.replace(/&lt;/ig, "<").replace(/&gt;/ig, ">").replace(/&amp;/ig, "&");
        }

        if(isOpera || isSafari) {
            var tempText = tempText.replace(/\r\n/g, "<br>").replace(/\n/g, "<br>").
            replace(/((\s*<[^\/][^>]*>\s*)*)([^<]*)((\s*<\/[^>]*>\s*)*)/g,
            function ($0, $1, $2, $3, $4, $5)
            {
                // Break long word to a new line, and include special chars.
                return $1 + escapeSpecialChars(escapeEntities($3).replace(/([^\s]{14})/g, "$1\n")).replace(/\n/g, "&#8203;") + $4;
            });
        }
        else if (!isIE) {
            var tempText = tempText.replace(/\r\n/g, "<br>").replace(/\n/g, "<br>").
            replace(/((\s*<[^\/][^>]*>\s*)*)([^<]*)((\s*<\/[^>]*>\s*)*)/g,
            function ($0, $1, $2, $3, $4, $5)
            {
                // Break long word to a new line, and include special chars.
                return $1 + escapeSpecialChars(escapeEntities($3).replace(/([^\s]{14})/g, "$1\n")).replace(/\n/g, "<wbr/>") + $4;
            });
        }

        return "<div style='width:200px;word-break:break-all;word-wrap:break-word;white-space:-moz-pre-wrap;overflow:hidden;' >" + tempText + "</div>";

    };

    /**
    * Utility function to apply visual styles to a com.gix.gui.Matrix object.  Useful when converting a standard
    * jsx3.gui.Matrix object to our prototype.  Simply edit the serialization file to make the class of the matrix
    * <code>com.gix.gui.Matrix</code>, then call this function on it to apply the visual styles to it, and save the file
    * again.
    */
    matrix.prototype.setDynamicProperties = function() {
        // set the dynamic property for this matrix

        this.setDynamicProperty("jsxbgcolor", "@addin@Matrix BG")
        jsx3.log("Set jsxbgcolo @addin@Matrix BG ")
        this.setDynamicProperty("jsxbg", "@addin@Matrix BG Image")
        jsx3.log("Set jsxbg @addin@Matrix BG Image")
        this.setDynamicProperty("jsxheaderheight", "@addin@Matrix HeaderHeight")
        jsx3.log("Set jsxheaderheight @addin@Matrix HeaderHeight")
        this.setDynamicProperty("jsxrowheight", "@addin@Matrix RowHeight")
        jsx3.log("Set jsxrowheight @addin@Matrix RowHeight")
        this.setDynamicProperty("jsxheaderborder", "@addin@Matrix HeaderBorder")
        jsx3.log("Set jsxheaderborder @addin@Matrix HeaderBorder")
        this.setDynamicProperty("jsxbodyborder", "@addin@Matrix BodyBorder")
        jsx3.log("Set jsxbodyborder @addin@Matrix BodyBorder")
        this.setDynamicProperty("jsxfocusstyle", "@addin@Matrix Focus Style")
        jsx3.log("Set jsxfocusstyle @addin@Matrix Focus Style")
        this.setDynamicProperty("jsxselectionbg", "@addin@Matrix Selection BG")
        jsx3.log("Set jsxselectionbg @addin@Matrix Selection BG")
        this.setDynamicProperty("jsxspystyle", "@addin@Matrix Spy Style")
        jsx3.log("Set jsxspystyle @addin@Matrix Spy Style")

        // set the XSL parameter
        this.setXSLParam("jsx_treehead_bgcolor", "#F3F3F3")
        this.setXSLParam("jsx_rowbg1", "#FFFFFF")
        this.setXSLParam("jsx_rowbg2", "#FFFFFF")
        this.setXSLParam("jsx_treehead_fontweight", "normal")

        //Set the spy glass
        if (!this.getCanSpy()) {
            this.setCanSpy = "true"
            if (!this.hasEvent("jsxspy"))
                this.setEvent("this.spyRecord(strRECORDID, objCOLUMN)","jsxspy")
        }

        // Set the properties for columns
        var clArry = this.getChildren();
        for (i = 0; i < clArry.length; i++) {

            if (clArry[i].instanceOf(jsx3.gui.Matrix.Column)) {
                clArry[i].setDynamicProperty("jsxfontname", "@addin@MatrixC Font Name")
                clArry[i].setDynamicProperty("jsxfontsize", "@addin@MatrixC Font Size")
                clArry[i].setDynamicProperty("jsxfontweight", "@addin@MatrixC Font Weight")
                clArry[i].setDynamicProperty("jsxcolor", "@addin@MatrixC Color")
                clArry[i].setDynamicProperty("jsxbgcolor", "@addin@MatrixC BGColor")
                clArry[i].setDynamicProperty("jsxbg", "@addin@MatrixC BackGround")
                clArry[i].setDynamicProperty("jsxpadding", "@addin@MatrixC Padding")
                clArry[i].setDynamicProperty("jsxborder", "@addin@MatrixC Border")

                clArry[i].setDynamicProperty("jsxcellfontname", "@addin@MatrixCell Font Name")
                clArry[i].setDynamicProperty("jsxcellfontsize", "@addin@MatrixCell Font Size")
                clArry[i].setDynamicProperty("jsxcellfontweight", "@addin@MatrixCell Font Weight")
                clArry[i].setDynamicProperty("jsxcellcolor", "@addin@MatrixCell Color")
                clArry[i].setDynamicProperty("jsxcellbgcolor", "@addin@MatrixCell BGColor")
                clArry[i].setDynamicProperty("jsxcellpadding", "@addin@MatrixCell Padding")
                if (i == clArry.length - 1) {
                    clArry[i].setDynamicProperty("jsxcellborder", "@addin@MatrixCell Border Last")
                }
                else {
                    clArry[i].setDynamicProperty("jsxcellborder", "@addin@MatrixCell Border")
                }
                // If it has a button mask
                var mask = clArry[i].getFirstChild()
                if (mask) {
                    if (mask.instanceOf(jsx3.gui.Button)) {
                        mask.setDynamicProperty("jsxfontname", "@addin@MatrixBTMask Font Name")
                        mask.setDynamicProperty("jsxfontsize", "@addin@MatrixBTMask Font Size")
                        mask.setDynamicProperty("jsxfontweight", "@addin@MatrixBTMask Font Weigh")
                        mask.setDynamicProperty("jsxcolor", "@addin@MatrixBTMask Color")
                        mask.setDynamicProperty("jsxdisabledcolor", "@addin@MatrixBTMask Disabled Color")
                        mask.setDynamicProperty("jsxbgcolor", "@addin@MatrixBTMask BGColor")
                        mask.setDynamicProperty("jsxdisabledbgcolor", "@addin@MatrixBTMask Disabled BGColor")
                        mask.setDynamicProperty("jsxpadding", "@addin@MatrixBTMask Padding")
                        mask.setDynamicProperty("jsxborder", "@addin@MatrixBTMask Border")
                        mask.setDynamicProperty("jsxclassname", "@addin@MatrixBTMask Css Rule Name")
                        mask.setDynamicProperty("jsxstyleoverride", "@addin@MatrixBTMask Css Override")
                    }
                }


            }
        }
    }


});